package com.hulman.oms.service;

import com.hulman.oms.bean.*;
import com.hulman.oms.dao.MaintainDao;
import com.hulman.oms.exception.IoTException;
import com.hulman.oms.util.DateUtil;
import com.hulman.oms.util.OrderUtil;
import com.hulman.oms.util.StringUtil;
import com.hulman.oms.util.SubjectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author: maxwellens
 */
@Service
public class MaintainService
{
    private static final String PROCESS_KEY = "maintain";

    /**
     * 审核通过
     */
    private static final Integer AUDIT_OK = 1;

    /**
     * 审核不通过
     */
    private static final Integer AUDIT_NG = 2;

    @Autowired
    private MaintainDao maintainDao;
    @Autowired
    private MaintainPlanService maintainPlanService;
    @Autowired
    private UserService userService;
    @Autowired
    private ProcInstService procInstService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private MsgService msgService;

    public List<Maintain> findMaintains(Map<String, Object> map)
    {
        return maintainDao.findMaintains(map);
    }

    public Integer findMaintainsCount(Map<String, Object> map)
    {
        return maintainDao.findMaintainsCount(map);
    }

    public Result findMaintainsResult(Map<String, Object> map)
    {
        Integer page = (Integer) map.get("page");
        Integer limit = (Integer) map.get("limit");
        if (page != null && limit != null)
        {
            map.put("start", (page - 1) * limit);
            map.put("length", limit);
        }
        int count = maintainDao.findMaintainsCount(map);
        List<Maintain> data = maintainDao.findMaintains(map);
        return new Result(data, count);
    }

    public Maintain findMaintainById(Integer id)
    {
        return maintainDao.findMaintainById(id);
    }

    public void saveMaintain(Maintain maintain)
    {
        if (maintain.getId() != null && maintain.getId() != 0)
        {
            maintainDao.updateMaintain(maintain);
        } else
        {
            maintainDao.insertMaintain(maintain);
        }
    }

    public void deleteMaintainById(Integer id)
    {
        maintainDao.deleteMaintainById(id);
    }

    /**
     * 创建保养工单
     */
    @Transactional(rollbackFor = Exception.class)
    public void create(Maintain maintain)
    {
        User createBy;
        if (StringUtil.isEmpty(maintain.getCreateByName()))
        {
            createBy = SubjectUtil.getUser();
            maintain.setCreateByName(createBy.getName());
        } else
        {
            createBy = userService.findUserByName(maintain.getCreateByName());
        }
        User director = userService.findUserByName(maintain.getDirectorName());
        //创建工单
        ProcInst procInst = procInstService.startProcess(PROCESS_KEY);
        maintain.setNo(OrderUtil.generate("BY"));
        maintain.setProcInstId(procInst.getId());
        maintain.setCreateTime(new Date());
        maintain.setCreateById(createBy.getId());
        maintain.setDirectorId(director.getId());
        maintain.setAuditTimes(0);
        maintain.setState(Maintain.STATE_EXECUTING);
        maintainDao.insertMaintain(maintain);
        //修改保养计划执行状态为执行中
        maintainPlanService.changeMaintainPlanState(maintain.getMaintainPlanId(), 1);
        //当前任务
        Task task1 = new Task();
        task1.setProcInstId(procInst.getId());
        task1.setOwnerId(createBy.getId());
        task1.setOwnerName(createBy.getName());
        task1.setName(procInst.getStateName());
        task1.setTag(PROCESS_KEY);
        task1.setFormKey(maintain.getId().toString());
        task1.addExtra("专项单号", maintain.getNo());
        task1.addExtra("专项名称", maintain.getName());
        taskService.createAndCompleteTask(task1);
        //下一个任务
        procInst = procInstService.next(procInst.getId());
        Task task2 = new Task();
        task2.setProcInstId(procInst.getId());
        task2.setOwnerId(director.getId());
        task2.setOwnerName(director.getName());
        task2.setName(procInst.getStateName());
        task2.setTag(PROCESS_KEY);
        task2.setFormKey(maintain.getId().toString());
        task2.addExtra("专项单号", maintain.getNo());
        task2.addExtra("专项名称", maintain.getName());
        task2.addExtra("创建人", maintain.getCreateByName());
        taskService.addTask(task2);
        task2.setPath("/pages/maintain/detail?taskId=" + task2.getId());
        task2.setPage("/maintain-info.html?taskId=" + task2.getId());
        taskService.saveTask(task2);
        msgService.sendMsg(task2.toMsg());
    }

    /**
     * 完成任务
     *
     * @param taskId
     * @param id
     * @param completion
     */
    @Transactional(rollbackFor = Exception.class)
    public void complete(Integer taskId, Integer id, String completion)
    {
        //修改工单
        Maintain maintain = maintainDao.findMaintainById(id);
        maintain.setCompletion(completion);
        maintain.setCompleteTime(new Date());
        maintain.setState(Maintain.STATE_AUDITING);
        maintainDao.updateMaintain(maintain);
        //完成本次任务
        taskService.createAndCompleteTask(taskId);
        ProcInst procInst = procInstService.next(maintain.getProcInstId());
        //让派发人审核
        Task task = new Task();
        task.setProcInstId(procInst.getId());
        task.setOwnerId(maintain.getCreateById());
        task.setOwnerName(maintain.getCreateByName());
        task.setName(procInst.getStateName());
        task.setTag(PROCESS_KEY);
        task.setFormKey(maintain.getId().toString());
        task.addExtra("专项单号", maintain.getNo());
        task.addExtra("保养内容", maintain.getName());
        taskService.addTask(task);
        task.setPath("/pages/maintain/detail?taskId=" + task.getId());
        task.setPage("/maintain-info.html?taskId=" + task.getId());
        taskService.saveTask(task);
        msgService.sendMsg(task.toMsg());
    }

    /**
     * 审核工单
     *
     * @param taskId
     * @param id
     * @param auditResult
     * @param auditComment
     * @param auditLocation
     * @param auditImgs
     */
    @Transactional(rollbackFor = Exception.class)
    public void audit(Integer taskId, Integer id, Integer auditResult, String auditComment, String auditLocation, String auditImgs)
    {
        User user = SubjectUtil.getUser();
        if (user == null)
        {
            throw new IoTException("用户未登陆");
        }
        Maintain maintain = maintainDao.findMaintainById(id);
        maintain.setAuditById(user.getId());
        maintain.setAuditByName(user.getName());
        maintain.setAuditResult(auditResult);
        maintain.setAuditComment(auditComment);
        maintain.setAuditLocation(auditLocation);
        maintain.setAuditImgs(auditImgs);
        maintain.setAuditTime(new Date());
        maintain.setAuditTimes(maintain.getAuditTimes() + 1);

        //修改下次保养日期
        MaintainPlan maintainPlan = maintainPlanService.findMaintainPlanById(maintain.getMaintainPlanId());
        maintainPlan.setNextMaintainDate(maintainPlan.calcNextMaintainDate(new Date()));
        maintainPlanService.saveMaintainPlan(maintainPlan);
        //修改保养计划执行状态为待执行
        maintainPlanService.changeMaintainPlanState(maintain.getMaintainPlanId(), 0);

        //完成本次任务
        taskService.createAndCompleteTask(taskId);

        if (maintain.getAuditResult() == AUDIT_OK)
        {
            maintain.setState(Maintain.STATE_DOCUMENTED);
            maintainDao.updateMaintain(maintain);
            procInstService.next(maintain.getProcInstId());
            //给负责人推送结果
            Msg msg = new Msg();
            msg.setType(Msg.TYPE_OM);
            msg.setOwnerId(maintain.getDirectorId());
            msg.setOwnerName(maintain.getDirectorName());
            msg.setTitle("专项保养单已审核");
            msg.addItem("保养内容", maintain.getName());
            msg.addItem("审核结果", maintain.getAuditResultText());
            msg.addItem("审核意见", maintain.getAuditComment());
            msg.addItem("审核时间", DateUtil.toDate(maintain.getAuditTime()));
            msgService.sendMsg(msg);
        } else if (auditResult == AUDIT_NG)
        {
            procInstService.pre(maintain.getProcInstId());
            maintain.setState(Maintain.STATE_EXECUTING);
            maintainDao.updateMaintain(maintain);
            //创建新的任务
            Task task = new Task();
            task.setProcInstId(maintain.getProcInstId());
            task.setOwnerId(maintain.getDirectorId());
            task.setOwnerName(maintain.getDirectorName());
            task.setName("审核不通过");
            task.setTag(PROCESS_KEY);
            task.setFormKey(maintain.getId().toString());
            task.addExtra("保养内容", maintain.getName());
            task.addExtra("审核意见", maintain.getAuditComment());
            taskService.addTask(task);
            task.setPath("/pages/maintain/detail?taskId=" + task.getId());
            task.setPath("/maintain-info.html?taskId=" + task.getId());
            taskService.saveTask(task);
            msgService.sendMsg(task.toMsg());
        }


    }

    /**
     * 撤销工单
     *
     * @param id 工单ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void terminate(Integer id)
    {
        //修改工单
        Maintain maintain = maintainDao.findMaintainById(id);
        maintain.setState(Maintain.STATE_TERMINATED);
        maintainDao.updateMaintain(maintain);
        //修改保养计划执行状态为待执行
        maintainPlanService.changeMaintainPlanState(maintain.getMaintainPlanId(), 0);
        //终止流程
        procInstService.terminate(maintain.getProcInstId());
    }

}
